package com.abso.mp3tunes.locker.core.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.dom4j.Element;

/**
 * The account data stores information about the user account.
 */
public class AccountData extends AbstractLockerData {

	/** The email address. */
	private String email;

	/** The user's nickname. */
	private String nickName;

	/** The user's first name. */
	private String firstName;

	/** The user's last name. */
	private String lastName;

	/** The maximum size (in bytes) of the Locker. */
	private long maxLockerSize;

	/** The current Locker size (in bytes). */
	private long currentLockerSize;

	/** The maximum file size (in bytes) allowed in the user's Locker. */
	private long maxFileSize;

	/** The Locker's type. */
	private String lockerType;

	/** The status value indicating if the Locker has expired. */
	private int expired;

	/** The list of subscriptions. */
	private List subscriptions;

	/**
	 * Constructs a new account data.
	 * 
	 * @param responseElem
	 *            the &lt;mp3tunes&gt; XML element.
	 */
	public AccountData(Element responseElem) {
		this.email = LockerDataUtils.getString(responseElem, "user/email");
		this.nickName = LockerDataUtils
				.getString(responseElem, "user/nickName");
		this.firstName = LockerDataUtils.getString(responseElem,
				"user/firstName");
		this.lastName = LockerDataUtils
				.getString(responseElem, "user/lastName");
		this.maxLockerSize = LockerDataUtils.getLong(responseElem,
				"user/maxLockerSize", -1);
		this.currentLockerSize = LockerDataUtils.getLong(responseElem,
				"user/currentLockerSize", -1);
		this.maxFileSize = LockerDataUtils.getLong(responseElem,
				"user/maxFileSize", -1);
		this.lockerType = LockerDataUtils.getString(responseElem,
				"user/lockerType");
		this.expired = LockerDataUtils.getInt(responseElem, "user/expired", -1);
		this.subscriptions = new ArrayList();
		for (Iterator i = responseElem.selectNodes("user/subscriptions/item")
				.iterator(); i.hasNext();) {
			Element subscriptionItem = (Element) i.next();
			subscriptions.add(new Subscription(subscriptionItem));
		}
		this.subscriptions = Collections.unmodifiableList(this.subscriptions);
	}

	/**
	 * Returns the email address.
	 * 
	 * @return the email address.
	 */
	public String getEmail() {
		return email;
	}

	/**
	 * Returns the user's nickname.
	 * 
	 * @return the user's nickname.
	 */
	public String getNickName() {
		return nickName;
	}

	/**
	 * Returns the user's first name.
	 * 
	 * @return the user's first name.
	 */
	public String getFirstName() {
		return firstName;
	}

	/**
	 * Returns the user's last name.
	 * 
	 * @return the user's last name.
	 */
	public String getLastName() {
		return lastName;
	}

	/**
	 * Returns the maximum size (in bytes) of the Locker.
	 * 
	 * @return the maximum size (in bytes) of the Locker.
	 */
	public long getMaxLockerSize() {
		return maxLockerSize;
	}

	/**
	 * Returns the current Locker size (in bytes).
	 * 
	 * @return the current Locker size (in bytes).
	 */
	public long getCurrentLockerSize() {
		return currentLockerSize;
	}

	/**
	 * Returns the maximum file size (in bytes) allowed in the user's Locker.
	 * 
	 * @return the maximum file size (in bytes).
	 */
	public long getMaxFileSize() {
		return maxFileSize;
	}

	/**
	 * Returns the Locker's type.
	 * 
	 * @return the Locker's type.
	 */
	public String getLockerType() {
		return lockerType;
	}

	/**
	 * Returns the status value indicating if the Locker has expired. For a
	 * non-expired Locker the returned value is <code>0</code>.
	 * 
	 * @return the expired status.
	 */
	public int getExpired() {
		return expired;
	}

	/**
	 * Returns the (immutable) list of subscriptions.
	 * 
	 * @return the (immutable) list of subscriptions.
	 */
	public List getSubscriptions() {
		return subscriptions;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see java.lang.Object#toString()
	 */
	public String toString() {
		return ToStringBuilder.reflectionToString(this,
				ToStringStyle.MULTI_LINE_STYLE);
	}

	/**
	 * The subscription level associated with a user's Locker.
	 */
	public static final class Subscription {

		/** The name of the subscription level. */
		private String name;

		/** The description of the subscription level. */
		private String description;

		/** The activation date of the subscription. */
		private Date activateDate;

		/** The expiration date of the subscription. */
		private Date expireDate;

		/**
		 * Constructs a new subscription.
		 * 
		 * @param item
		 *            the &lt;item&gt; XML element.
		 */
		public Subscription(Element item) {
			this.name = LockerDataUtils.getString(item, "name");
			this.description = LockerDataUtils.getString(item, "description");
			this.activateDate = LockerDataUtils.getDate(item, "activateDate");
			this.expireDate = LockerDataUtils.getDate(item, "expireDate");
		}

		/**
		 * Returns the name of the subscription level.
		 * 
		 * @return the name of the subscription level.
		 */
		public String getName() {
			return name;
		}

		/**
		 * Returns the name of the subscription level.
		 * 
		 * @return the description of the subscription level.
		 */
		public String getDescription() {
			return description;
		}

		/**
		 * Returns the activation date of the subscription.
		 * 
		 * @return the activation date.
		 */
		public Date getActivateDate() {
			return activateDate;
		}

		/**
		 * Returns the expiration date of the subscription.
		 * 
		 * @return the expiration date.
		 */
		public Date getExpireDate() {
			return expireDate;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Object#toString()
		 */
		public String toString() {
			return ToStringBuilder.reflectionToString(this,
					ToStringStyle.MULTI_LINE_STYLE);
		}

	}

}
